package com.apes.fn.scm.retailReturn;

import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.AccountingMethod;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @BelongsProject: apes-server
 * @BelongsPackage: com.apes.fn.scm.retailReturn
 * @ClassName: NoInventoryRetailReturnItemsService
 * @Author: pyb
 * @CreateTime: 2020-05-07 17:15
 * @Description: 零售退货带安/服务商品流转凭证服务
 * @Version: 1.0
 */
@Service("noInventoryRetailReturnItemsService")
public class NoInventoryRetailReturnItemsService extends DomainService {

    @Autowired
    private VoucherRepository voucherRepository;

    @Autowired
    private RetailReturnRepository retailReturnRepository;

    @Autowired
    private InventoryService inventoryService;

    /**
     * 生成零售返厂凭证
     *
     * @param request
     * @return
     */
    public RetailReturn process(SimpleRequest request) {
        RetailReturn retailReturn = request.getO(RetailReturn.class);
        retailReturn = retailReturnRepository.findOne(retailReturn.getId());
        if (!retailReturn.getState().equals("done")) {
            throw new RuntimeException("零售退回订单状态不对！");
        }
        if ("B".equals(retailReturn.getOrderType().getCode())) {
            // 没有原始订单零售退货项目流程
            noOriginalOrderRetailReturnItemsProcess(retailReturn);
        } else {
            // 有原始订单零售退货项目流程

            // 服务商品(非带安、油漆商品)  0元采购返厂
            autRetailItemsProcess(retailReturn);
        }
        return retailReturn;
    }

    /**
     * 无原单零售退货(无库存)项目流程
     *
     * @param retailReturn
     */
    private void noOriginalOrderRetailReturnItemsProcess(RetailReturn retailReturn) {
        Map<PartyRole, List<RetailReturnItem>> returnItems = retailReturn.getSaleItems().stream()
                .filter(item -> item.getProduct().getType().equals("aut"))
                .collect(Collectors.groupingBy(RetailReturnItem::getOwner));
        if (returnItems.isEmpty()) return;

        returnItems.forEach((company, v) -> {
            Voucher voucher = getDefaultVoucher(retailReturn, BusinessType.SALE_RETURN);
            voucher.setCompany(company);
            //取无原单零售单上的客户
            voucher.setPartner(retailReturn.getCustomer());

            // 查找代销合同（目前采购结算按照合同）
            voucher.setInventoryMode(InventoryMode.IM_OWN);     //设置库存模式：自有
            voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);  // 核算方式：经销
            voucher.setVoucherItems(
                    v.stream().map(
                            item -> {
                                // 无原单不指定供应商和销售批次
                                VoucherItem voucherItem = new VoucherItem();
                                voucherItem.setProduct(item.getProduct());
                                voucherItem.setTax(item.getTax());
                                voucherItem.setOwner(item.getOwner());

                                // 设置为销售的单位以及数量
                                voucherItem.setUom(item.getUom());
                                voucherItem.setProductQty(-1.00 * item.getProductUomQty());

                                // 默认为零售单价
                                voucherItem.setPriceUnit(item.getPriceUnit());
                                voucherItem.setOriginItemId(item.getId());
                                voucherItem.setSourceItemId(item.getId());

                                return voucherItem;
                            }
                    ).collect(Collectors.toSet())
            );
            createVoucher(voucher);
        });
    }


    /**
     * 服务商品(非经销、代销、油漆)
     *    实物商品不做返厂
     * @param retailReturn RetailReturn
     */
    private void autRetailItemsProcess(RetailReturn retailReturn) {
        // 服务商品
        List<RetailReturnItem> retailReturnItems = retailReturn.getSaleItems().stream()
                .filter(item -> item.getRetailOrderItem().getProductRule() == 30 && !item.getRetailOrderItem().isPaintFlag())
                .collect(Collectors.toList());

        if (!retailReturnItems.isEmpty()) {
            createPurchaseReturnVoucher(retailReturn, retailReturnItems);
        }
    }

    /**
     * 生成零售服务商品返厂凭证
     *
     * @param retailReturn RetailReturn
     * @param items        过滤后明细
     */
    private void createPurchaseReturnVoucher(RetailReturn retailReturn, List<RetailReturnItem> items) {
        // 获取原销售凭证
        Voucher source = voucherRepository.findOne(
                JpaDsl.toCriteriaByEq("sourceBusinessType", RetailReturn.class.getSimpleName(), "source", retailReturn.getId(), "voucherType", "CUSTOMER_SALE"))
                .orElseThrow(() -> new RuntimeException("没有找到退货原单：" + retailReturn.getId() + " 的业务凭证！"));

        Map<String, VoucherItem> voucherItemMap = source.getVoucherItems().stream().collect(Collectors.toMap(VoucherItem::getSourceItemId, voucherItem -> voucherItem));

        //构建凭证明细
        Set<VoucherItem> voucherItemSet = items.stream().map(item -> {
            VoucherItem voucherItem = new VoucherItem();
            voucherItem.setProduct(item.getProduct());
            voucherItem.setOwner(item.getOwner());
            voucherItem.setUom(item.getUom());
            voucherItem.setProductQty(-1.00 * item.getProductUomQty());
            voucherItem.setOriginItemId(String.valueOf(item.getId()));
            voucherItem.setSourceItemId(String.valueOf(item.getId()));

            // 获取原销售批次
            VoucherInventory voucherInventory = SpringManager.getBean(VoucherInventoryRepository.class)
                    .findAll(JpaDsl.toCriteriaByEq("voucher.id", source.getId(), "voucherItem", voucherItemMap.get(item.getId()).getId())).stream().findFirst().get();
            InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();
            voucherItem.setInventoryBatch(inventoryBatch);
            voucherItem.setPriceUnit(inventoryBatch.getTaxCostPrice());
            voucherItem.setSupplier(inventoryBatch.getSupplier());
            voucherItem.setTax(inventoryBatch.getTax());

            //  增加（减少）冻结数量
            inventoryService.changeFrostQty(inventoryBatch, item.getUom(), item.getProductUomQty(), inventoryBatch.getCompany(),
                    source.getInnerBusinessType(), source.getId(), item.getId(), "生成零售带安服务商品返厂凭证");

            return voucherItem;
        }).collect(Collectors.toSet());

        // 根据合同分组
        Map<Contract, List<VoucherItem>> contractListMap = voucherItemSet.stream().collect(Collectors.groupingBy(x -> x.getInventoryBatch().getContract()));
        contractListMap.forEach((k, v) -> {
            Voucher voucher = new Voucher();
            voucher.setInventoryMode(k.getCooperation().getInventoryMode());
            voucher.setAccountingMethod(k.getCooperation().getAccountingMethod());
            voucher.setReturned(true);
            voucher.setCompany(retailReturn.getCompany());
            voucher.setBusinessType(BusinessType.PURCHASE_RETURN);
            voucher.setDept(retailReturn.getDept());
            voucher.setClerk(retailReturn.getClerk());
            voucher.setPartner(k.getPartner());
            voucher.setContract(k);
            voucher.setScene(retailReturn.getScene());
            voucher.setOrigin(retailReturn.getId());
            voucher.setOriginBusinessType(retailReturn.getInnerBusinessType());
            voucher.setSource(retailReturn.getId());
            voucher.setSourceBusinessType(retailReturn.getInnerBusinessType());
            // 从表信息
            voucher.setVoucherItems(new HashSet<VoucherItem>(v));
            Voucher newVoucher = createVoucher(voucher);
            if (newVoucher.getInventoryMode().equals("IM_OWN")) {
                //生成账单
                invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(newVoucher))));
            }
        });

    }

    // 生成凭证
    private Voucher createVoucher(Voucher voucher) {
        return invoke("voucher.create", MapUtil.mapped(voucher));
    }

    /**
     * 构建凭证主体
     *
     * @param retailReturn
     * @param businessType
     * @return
     */
    private Voucher getDefaultVoucher(RetailReturn retailReturn, String businessType) {
        Voucher voucher = new Voucher();
        voucher.setReturned(true);
        voucher.setCompany(retailReturn.getCompany());
        voucher.setBusinessType(businessType);
        voucher.setDept(retailReturn.getDept());
        voucher.setClerk(retailReturn.getClerk());
        voucher.setPartner(retailReturn.getCompany().getParty().getPatyRoleByType("Customer"));
        voucher.setScene(retailReturn.getScene());
        voucher.setOrigin(retailReturn.getId());
        voucher.setOriginBusinessType(retailReturn.getInnerBusinessType());
        voucher.setSource(retailReturn.getId());
        voucher.setSourceBusinessType(retailReturn.getInnerBusinessType());
        return voucher;
    }
}
